﻿namespace DafYomiLib
{
    using System;
    using System.Globalization;


    public class DafYomiDetails
    {
        public DafYomiDetails(Tractate tractate, int page)
        {
            var tractateDetails = TalmudBavli.TractatesDetails[tractate];

            if (page < tractateDetails.FirstPageNumber)
            {
                throw new ArgumentOutOfRangeException(
                    "page",
                    string.Format(CultureInfo.InvariantCulture, "Page value of {0} for tractate '{1}' is lower than first page '{2}'", page, tractate, tractateDetails.LastPageNumber));
            }

            if (page > tractateDetails.LastPageNumber)
            {
                throw new ArgumentOutOfRangeException(
                    "page",
                    string.Format(CultureInfo.InvariantCulture, "Page value of {0} for tractate '{1}' is higher than last page '{2}'", page, tractate, tractateDetails.LastPageNumber));
            }

            Tractate = tractate;
            Page = page;
        }

        public Tractate Tractate { get; private set; }

        public int Page { get; private set; }
    }

    public class DafYomi
    {
        private readonly DateTime m_firstDafYomiDate = // new DateTime(1923, 9, 11);
            new DateTime(2012, 8, 3);

        private CultureInfo m_hebrewCulture = new CultureInfo("he-IL");
        private HebrewCalendar m_hebrewCalendar = new HebrewCalendar();

        public static int NumberOfFullPagesInTalmudBavli
        {
            get { return 2711; }
        }

        public DafYomiDetails TodayDafYomi
        {
            get
            {
                var today = DateTime.Today;
                var firstPeriodDate = GetFirstPeriodDateByDateInPeriod(today);
                var daysFromPeriodStart = today - firstPeriodDate;

                return new DafYomiDetails(Tractate.Arachin, 2);
            }
        }

        public DafYomiDetails GetDafYomiOfDate(DateTime dateToGetDafYomiFor)
        {
            var firstPeriodDate = GetFirstPeriodDateByDateInPeriod(dateToGetDafYomiFor);

            // Calc the difference between requested date and the beginning of the new current iteration of Daf Yomi
            // The +1 is needed because we want it to be one based (not zero based) - first day in iteration = 1 not 0.
            var dayNumberInPeriod = (int)(dateToGetDafYomiFor - firstPeriodDate).TotalDays + 1;
            var dayFromTractateStart = dayNumberInPeriod;
            foreach (var tractateDetails in TalmudBavli.TractatesDetails.Values)
            {
                if (dayFromTractateStart > tractateDetails.NumberOfDoubledPages)
                {
                    dayFromTractateStart -= tractateDetails.NumberOfDoubledPages;
                }
                else
                {
                    return new DafYomiDetails(tractateDetails.Tractate, dayFromTractateStart + 1);
                }
            }

            throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
                                                                  "Could not find Daf Yomi details for date (mm/dd/YYYY): {0}",
                                                                  dateToGetDafYomiFor.Date));
        }

        private DateTime GetFirstPeriodDateByDateInPeriod(DateTime dateInPeriod)
        {
            DateTime firstPeriodDate = m_firstDafYomiDate;
            while ((dateInPeriod - firstPeriodDate).TotalDays >= NumberOfFullPagesInTalmudBavli)
            {
                firstPeriodDate = firstPeriodDate.AddDays(NumberOfFullPagesInTalmudBavli);
            }

            return firstPeriodDate;
        }
    }
}
